package com.wangy.database.util;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.wangy.database.annotation.Column;
import com.wangy.database.annotation.Entity;
import com.wangy.database.annotation.Id;
import com.wangy.database.bean.ColumnInfo;
import com.wangy.database.bean.PrimaryKeyInfo;
import com.wangy.utils.StringUtil;

public class TableUtil {

	public static String getTableName(Class<?> clazz) {
		String tableName = null;
		if (clazz.isAnnotationPresent(Entity.class)) {
			Entity entity = clazz.getAnnotation(Entity.class);
			if (StringUtil.isNotNullAndEmpty(entity.name())) {
				tableName = entity.name();
			} else if (StringUtil.isNotNullAndEmpty(entity.value())) {
				tableName = entity.value();
			}
		} else {
			tableName = clazz.getSimpleName();
		}
		return tableName;
	}

	public static List<ColumnInfo> getColumnInfo(Class<?> clazz) {
		List<ColumnInfo> columnInfos = null;
		Field[] fields = clazz.getDeclaredFields();
		String columnName = null;
		String fieldName = null;
		if (fields.length <= 0) {
			return null;
		}
		columnInfos = new ArrayList<ColumnInfo>();
		for (Field field : fields) {
			fieldName = field.getName();
			columnName = fieldName;
			if (field.isAnnotationPresent(Column.class)) {
				fieldName = field.getName();
				Column column = field.getAnnotation(Column.class);
				if (StringUtil.isNotNullAndEmpty(column.name())) {
					columnName = column.name();
				} else if (StringUtil.isNotNullAndEmpty(column.value())) {
					columnName = column.value();
				} 
			}
			columnInfos.add(new ColumnInfo(columnName, fieldName));

		}
		return columnInfos;
	}

	public static List<PrimaryKeyInfo> getPrimaryKey(Class<?> clazz) {
		List<PrimaryKeyInfo> primaryKeyInfos = null;
		Field[] fields = clazz.getDeclaredFields();
		String columnName = null;
		String fieldName = null;
		if (fields.length <= 0) {
			return null;
		}
		primaryKeyInfos = new ArrayList<PrimaryKeyInfo>();
		for (Field field : fields) {
			fieldName = field.getName();
			if (field.isAnnotationPresent(Column.class)) {
				Id id = field.getAnnotation(Id.class);
				if (StringUtil.isNotNullAndEmpty(id.name())) {
					columnName = id.name();
				} else if (StringUtil.isNotNullAndEmpty(id.value())) {
					columnName = id.value();
				} else {
					columnName = fieldName;
				}
				primaryKeyInfos.add(new PrimaryKeyInfo(columnName, fieldName));
			}

		}
		return primaryKeyInfos;
	}

	public static List<ColumnInfo> getAll(Class<?> clazz) {
		List<ColumnInfo> columnInfos = null;
		Field[] fields = clazz.getDeclaredFields();
		String columnName = null;
		String fieldName = null;
		if (fields.length <= 0) {
			return null;
		}
		columnInfos = new ArrayList<ColumnInfo>();
		for (Field field : fields) {
			fieldName = field.getName();
			columnName = fieldName;
			if (field.isAnnotationPresent(Column.class)) {
				Column column = field.getAnnotation(Column.class);
				if (StringUtil.isNotNullAndEmpty(column.name())) {
					columnName = column.name();
				} else if (StringUtil.isNotNullAndEmpty(column.value())) {
					columnName = column.value();
				}
			} else if (field.isAnnotationPresent(Column.class)) {
				fieldName = field.getName();
				Id id = field.getAnnotation(Id.class);
				if (StringUtil.isNotNullAndEmpty(id.name())) {
					columnName = id.name();
				} else if (StringUtil.isNotNullAndEmpty(id.value())) {
					columnName = id.value();
				}
			} 
			columnInfos.add(new ColumnInfo(columnName, fieldName));
		}
		return columnInfos;
	}

	public static <T> List<T> getEntityList(Class<T> clazz, ResultSet rs) {
		T entity = null;
		List<T> list = new ArrayList<T>();
		List<ColumnInfo> columnInfos = TableUtil.getAll(clazz);
		try {
			while (rs.next()) {
				entity = clazz.newInstance();
				for (ColumnInfo columnInfo : columnInfos) {
					Field field = clazz.getDeclaredField(columnInfo.getFieldName());
					field.setAccessible(true);
					field.set(entity, rs.getObject(columnInfo.getColumnName()));
				}
				list.add(entity);
			}
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} 
		return list;
	}

	public static <T> T getEntity(Class<T> clazz, ResultSet rs) {
		T entity = null;
		List<ColumnInfo> columnInfos = TableUtil.getAll(clazz);
		try {
			rs.next();
			entity = clazz.newInstance();
			for (ColumnInfo columnInfo : columnInfos) {
				Field field = clazz.getDeclaredField(columnInfo.getFieldName());
				field.setAccessible(true);
				field.set(entity, rs.getObject(columnInfo.getColumnName()));
			}
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} 
		return entity;
	}

	public static <T> T getEntity(Class<T> clazz, Map<String, Object> map) {
		T entity = null;
		List<ColumnInfo> columnInfos = TableUtil.getAll(clazz);
		try {
			entity = clazz.newInstance();
			for (ColumnInfo columnInfo : columnInfos) {
				if (map.containsKey(columnInfo.getColumnName())) {
					Field field = clazz.getDeclaredField(columnInfo.getFieldName());
					field.setAccessible(true);
					field.set(entity, map.get(columnInfo.getColumnName()));
				}
			}
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
		return entity;
	}

}
